package com.icons.draw.view;

import java.util.Iterator;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

import com.blahti.example.drag2.DragActivityV2;
import com.blahti.example.drag2.R;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
import com.icons.draw.*;

import data.*;

public class MapLocationOverlay  extends Overlay {

	/**
	 * Stored as global instances as one time initialization is enough
	 */
	private Bitmap car,resizedBitmap,resizedBitmap2,parkSignal;// mShadowIcon,resizedBitmap;

	private LocationViewers mLocationViewers;
	private Paint	mInnerPaint, mBorderPaint, mTextPaint;
	private MapLocation PreHitMapLocation = null;
	public String userStreet="";


	ParkingSpotsList parkingResult;
	ParkingDB parking_db;
	String street;
	String side;
	int index=-1;
	SharedPreferences.Editor ed;
	SharedPreferences ref;
	double angle=0;
	double tmpAngle=-1;
	double curAngle=0;

	/**
	 * It is used to track the visibility of information window and clicked location is known location or not 
	 * of the currently selected Map Location
	 */
	private MapLocation mSelectedMapLocation;  

	public MapLocationOverlay(LocationViewers mLocationViewers,MapView mapView) {

		this.mLocationViewers = mLocationViewers;
		parking_db=ParkingDB.getInstance();
		car = BitmapFactory.decodeResource(mLocationViewers.getResources(),R.drawable.bimba);
		parkSignal=BitmapFactory.decodeResource(mLocationViewers.getResources(),R.drawable.signal);
		//mShadowIcon = BitmapFactory.decodeResource(mLocationViewers.getResources(),R.drawable.shadow);
		//mapView.invalidate();
		Log.d("-----------------------------","MapLocationOverlay");

	}


	@Override
	public boolean onTap(GeoPoint p, MapView mapView)  {

		Log.d("-----------------------------","onTap1");

		/**
		 * Track the popup display
		 */
		boolean isRemovePriorPopup = mSelectedMapLocation != null; 

		/**
		 * Test whether a new popup should display
		 */

		PreHitMapLocation=mSelectedMapLocation;
		mSelectedMapLocation = getHitMapLocation(mapView,p);
		//Coordinate userLoc;
		if(PreHitMapLocation!=null)
		{
			if(PreHitMapLocation==mSelectedMapLocation)
			{
       
			}
		}
		else
			if ( isRemovePriorPopup || mSelectedMapLocation != null) {
				Log.d("-----------------------------","omTap");

				mapView.invalidate();
			}



		/**
		 *   Return true if we handled this onTap()
		 */

		return mSelectedMapLocation != null;
	}




	@Override
	public void draw(Canvas canvas, MapView	mapView, boolean shadow) {

		//drawInfoWindow(canvas, mapView, shadow);
		if(parking_db.serverOn)
			drawParkingSpots( canvas,  mapView, shadow);
		drawMapLocations(canvas, mapView, shadow);

		if(parking_db.myParking==true)
		{
			
			drawPark(canvas,  mapView, shadow);
			
		}
		Log.d("-----------------------------","draw");

	}

	/**
	 * Test whether an information balloon should be displayed or a prior balloon hidden.
	 */
	private MapLocation getHitMapLocation(MapView	mapView, GeoPoint	tapPoint) {

		/**
		 *   Tracking the clicks on MapLocation
		 */
		MapLocation hitMapLocation = null;

		RectF hitTestRecr = new RectF();
		Point screenCoords = new Point();
		MapLocation testLocation;
		
		if((parking_db.curLoc!=null)&&(parking_db.gps))
		    testLocation =parking_db.curLoc;
		else
			testLocation =parking_db.noGpsLoc;

			

		/**
		 * This is used to translate the map's lat/long coordinates to screen's coordinates
		 */
		mapView.getProjection().toPixels(testLocation.getPoint(), screenCoords);

		// Create a testing Rectangle with the size and coordinates of our icon
		// Set the testing Rectangle with the size and coordinates of our on screen icon
		hitTestRecr.set(-resizedBitmap.getWidth()/2,-resizedBitmap.getHeight(),resizedBitmap.getWidth()/2,0);
		hitTestRecr.offset(screenCoords.x,screenCoords.y);


		//  At last test for a match between our Rectangle and the location clicked by the user
		mapView.getProjection().toPixels(tapPoint, screenCoords);
		if (hitTestRecr.contains(screenCoords.x,screenCoords.y)) {
			hitMapLocation = testLocation;
			//break;
		}
		//}

		//  Finally clear the new MouseSelection as its process finished
		tapPoint = null;

		return hitMapLocation; 
	}
	private void drawPark(Canvas canvas, MapView mapView, boolean shadow)
	{
		Point screenCoords = new Point();
		double lat=parking_db.mySpotLat;
		double longi=parking_db.mySpotLong;
		GeoPoint newp=new GeoPoint((int)(lat*1E6),(int)(longi*1E6));
		mapView.getProjection().toPixels(newp,screenCoords);
		int width = parkSignal.getWidth();
		int height = parkSignal.getHeight();
		int newWidth =35;
		int newHeight =35;

		// calculate the scale - in this case = 0.4f
		float scaleWidth = ((float) newWidth) / width;
		float scaleHeight = ((float) newHeight) / height;

		// createa matrix for the manipulation
		Matrix matrix = new Matrix();
		// resize the bit map
		matrix.postScale(scaleWidth, scaleHeight);
		

		resizedBitmap2 = Bitmap.createBitmap(parkSignal, 0, 0, 
				width, height, matrix, true); 

		canvas.drawBitmap(resizedBitmap2, screenCoords.x-resizedBitmap2.getWidth()/2, screenCoords.y - resizedBitmap2.getHeight()/2,null);
		
	}

	private void drawMapLocations(Canvas canvas, MapView mapView, boolean shadow) {

		Point screenCoords = new Point();
		Point tmp = new Point();/////////
		MapLocation location;
		if((parking_db.curLoc!=null)&&(parking_db.gps))
		{
			 location =parking_db.curLoc;
			 mapView.getProjection().toPixels(location.getPoint(), screenCoords);
		}
		else
			 location =parking_db.noGpsLoc;
			 mapView.getProjection().toPixels(location.getPoint(), screenCoords);

		if(parking_db.preLoc!=null)
			mapView.getProjection().toPixels(parking_db.preLoc.getPoint(), tmp);//////////


		if (shadow) {
			// Offset the shadow in the y axis as it is angled, so the base is at x=0
			//canvas.drawBitmap(mShadowIcon, screenCoords.x, screenCoords.y - mShadowIcon.getHeight(),null);
		} 
		else {

			int width = car.getWidth();
			int height = car.getHeight();
			int newWidth =35;
			int newHeight =35;

			// calculate the scale - in this case = 0.4f
			float scaleWidth = ((float) newWidth) / width;
			float scaleHeight = ((float) newHeight) / height;

			// createa matrix for the manipulation
			Matrix matrix = new Matrix();
			// resize the bit map
			matrix.postScale(scaleWidth, scaleHeight);
			// rotate the Bitmap

			String msg= "cur: "
					+ String.format("%d", screenCoords.x)+" , "+String.format("%d", screenCoords.y) +"\n";
			// Toast.makeText (LocationViewers.mapView.getContext(), msg, Toast.LENGTH_LONG).show ();
			if(parking_db.preLoc!=null)
			{
				msg= "pre: "
						+ String.format("%d", tmp.x)+" , "+String.format("%d", tmp.y) +"\n";
				//Toast.makeText (LocationViewers.mapView.getContext(), msg, Toast.LENGTH_LONG).show ();
			}
			//else
				//Toast.makeText (LocationViewers.mapView.getContext(), "null", Toast.LENGTH_LONG).show ();


			float angle=(float) calculateCarAngle(mapView);
			msg= "angle: "
					+ String.format("%f", angle)+"\n";
			//   Toast.makeText (LocationViewers.mapView.getContext(), msg, Toast.LENGTH_LONG).show ();
			matrix.postRotate(angle );
			// matrix.postRotate(0);
			// recreate the new Bitmap
			resizedBitmap = Bitmap.createBitmap(car, 0, 0, 
					width, height, matrix, true); 


			// bmd.draw(canvas);
			canvas.drawBitmap(resizedBitmap, screenCoords.x-resizedBitmap.getWidth()/2, screenCoords.y - resizedBitmap.getHeight()/2,null);
			//canvas.drawBitmap(car, screenCoords.x - car.getWidth()/2, screenCoords.y - car.getHeight(),null);
		}
	}
	//}

	public void drawParkingSpots(Canvas canvas, MapView mapView, boolean shadow){
		Paint   mPaint = new Paint();
		mPaint.setDither(true);
		mPaint.setColor(Color.RED);
		mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
		mPaint.setStrokeWidth(5);

		Projection projection = mapView.getProjection();
		//  parkingVector=mLocationViewers.getParkingVectore();

		if(parking_db.parkingVector==null)
		{
			Log.d("error MapLocationOverlay","parking vector is null");

		}

		if(parking_db.parkingVector!=null)
		{
			for(int j=0;j<parking_db.parkingVector.size();j++)
			{
				parkingResult=parking_db.parkingVector.get(j);
				for(int i=0;i<parkingResult.list.size();i++)
				{
					GeoPoint g1=new GeoPoint((int) (parkingResult.list.get(i).parkingCordinate_A.latitude* 1e6),
							(int) ( parkingResult.list.get(i).parkingCordinate_A.longitude* 1e6));
					GeoPoint g2=new GeoPoint((int) (parkingResult.list.get(i).parkingCordinate_B.latitude* 1e6),
							(int) ( parkingResult.list.get(i).parkingCordinate_B.longitude* 1e6));
					Point p1 = new Point();
					Point p2 = new Point();
					projection.toPixels(g1, p1);
					projection.toPixels(g2, p2);
					Path path = new Path();
					switch (parkingResult.list.get(i).parkingStatus)
					{
					case 0:  mPaint.setColor(Color.BLUE);   break;
					case 1:  mPaint.setColor(Color.RED);    break;
					case 2:  mPaint.setColor(Color.YELLOW); break;
					default: mPaint.setColor(Color.BLACK);  break;
					}

					path.moveTo(p1.x, p1.y);
					path.lineTo(p2.x,p2.y);
					canvas.drawPath(path, mPaint);
				}

			}
		}
	}

	private void drawInfoWindow(Canvas canvas, MapView	mapView, boolean shadow) {

		if ( mSelectedMapLocation != null) {
			if ( shadow) {
				//  Skip painting a shadow
			} else {
				//  First we need to determine the screen coordinates of the selected MapLocation
				Point selDestinationOffset = new Point();
				mapView.getProjection().toPixels(mSelectedMapLocation.getPoint(), selDestinationOffset);

				//  Setup the info window
				int INFO_WINDOW_WIDTH = 175;
				int INFO_WINDOW_HEIGHT = 40;
				RectF infoWindowRect = new RectF(0,0,INFO_WINDOW_WIDTH,INFO_WINDOW_HEIGHT);				
				int infoWindowOffsetX = selDestinationOffset.x-INFO_WINDOW_WIDTH/2;
				int infoWindowOffsetY = selDestinationOffset.y-INFO_WINDOW_HEIGHT-resizedBitmap.getHeight();
				infoWindowRect.offset(infoWindowOffsetX,infoWindowOffsetY);

				//  Drawing the inner info window
				canvas.drawRoundRect(infoWindowRect, 5, 5, getmInnerPaint());

				//  Drawing the border for info window
				canvas.drawRoundRect(infoWindowRect, 5, 5, getmBorderPaint());

				//  Draw the MapLocation's name
				int TEXT_OFFSET_X = 10;
				int TEXT_OFFSET_Y = 15;
				canvas.drawText(mSelectedMapLocation.getName(),infoWindowOffsetX+TEXT_OFFSET_X,infoWindowOffsetY+TEXT_OFFSET_Y,getmTextPaint());
			}
		}
	}

	public Paint getmInnerPaint() {
		if ( mInnerPaint == null) {
			mInnerPaint = new Paint();
			mInnerPaint.setARGB(225, 50, 50, 50); //inner color
			mInnerPaint.setAntiAlias(true);
		}
		return mInnerPaint;
	}

	public Paint getmBorderPaint() {
		if ( mBorderPaint == null) {
			mBorderPaint = new Paint();
			mBorderPaint.setARGB(255, 255, 255, 255);
			mBorderPaint.setAntiAlias(true);
			mBorderPaint.setStyle(Style.STROKE);
			mBorderPaint.setStrokeWidth(2);
		}
		return mBorderPaint;
	}

	public Paint getmTextPaint() {
		if ( mTextPaint == null) {
			mTextPaint = new Paint();
			mTextPaint.setARGB(255, 255, 255, 255);
			mTextPaint.setAntiAlias(true);
		}
		return mTextPaint;
	}



	


	double calculateCarAngle(MapView mapView)
	{
		double a;
		double b;
		int quarter=0;

		if(parking_db.preLoc!=null)
		{
			Point cur = new Point();
			if((parking_db.curLoc!=null)&&(parking_db.gps))
			   mapView.getProjection().toPixels(parking_db.curLoc.getPoint(), cur);
			else
			   mapView.getProjection().toPixels(parking_db.noGpsLoc.getPoint(), cur);
			Point pre = new Point();
			mapView.getProjection().toPixels(parking_db.preLoc.getPoint(), pre);

			if(pre.x==cur.x){
				if(pre.y>cur.y)
					return 180;
				else
					return 0;
			}
			if(pre.y==cur.y)
			{
				if(pre.x>cur.x)
					return 90;
				else
					return 270;
			}

			if((pre.x<cur.x)&&(pre.y>cur.y))
			{
				quarter=1;
			}
			else
				if((pre.x<cur.x)&&(pre.y<cur.y))
				{
					quarter=2;
				}
				else
					if((pre.x>cur.x)&&(pre.y<cur.y))
					{
						quarter=3;
					}
					else
						if((pre.x>cur.x)&&(pre.y>cur.y))
						{
							quarter=4;
						}
						else
							return angle;


			Point tmp = new Point();

			if(quarter%2!=0)
			{
				tmp.x=pre.x;
				tmp.y=cur.y;	
			}
			else
			{
				tmp.x=cur.x;
				tmp.y=cur.y;
			}


			String msg= "cur: "
					+ String.format("%d", cur.x)+" , "+String.format("%d", cur.y) +"\n";
			///Toast.makeText (LocationViewers.mapView.getContext(), msg, Toast.LENGTH_LONG).show ();

			a=Math.sqrt(Math.pow(cur.x-pre.x ,2)+Math.pow(cur.y-pre.y ,2)); 
			b=Math.sqrt(Math.pow(cur.x-tmp.x ,2)+Math.pow(cur.y-tmp.y ,2));

			if(b<a) 
			{
				angle=(float) Math.asin((b/a));
				return angle +90*(quarter-1);
			}

		}
        if(Math.abs(angle-curAngle)<20) //same direction
        {
        	curAngle=angle;        	
        }
        else
        if((tmpAngle!=-1)&&(Math.abs(angle-tmpAngle)<20))//direction was changed
        {
        	curAngle=angle;
        }
        else                           // not sure if direction changed 
        {
        	tmpAngle=angle;
        	
        }
		return curAngle;
	}
}